import { asyncRoutes, constantRoutes } from '@/router'

/**
 * Use meta.role to determine if the current user has permission
 * @param roles
 * @param route
 */
/*
* 这段代码是一个 JavaScript 函数，名为 hasPermission。它接受两个参数：roles 和 route。roles 是一个数组，包含用户所具有的角色，而 route 是一个对象，表示应用程序的路由。

该函数的作用是检查当前用户是否具有访问特定路由的权限。函数会首先检查路由对象的 meta 属性是否存在，以及 meta 对象中是否有一个名为 roles 的属性。如果存在，
* 函数将遍历 roles 数组，检查其中是否有任何一个角色包含在 route.meta.roles 数组中。如果是，则函数返回 true，表示用户有权限访问该路由；
* 否则，函数返回 false，表示用户无权限访问该路由。如果路由对象没有 meta 属性或者 meta 对象中没有 roles 属性，则默认返回 true，即用户具有访问该路由的权限。

该函数的实现依赖于 JavaScript 中的 Array.prototype.some() 和 Array.prototype.includes() 方法
* 。Array.prototype.some() 方法用于检查数组中是否有一个元素符合指定的条件，它会返回一个布尔值。
* 而 Array.prototype.includes() 方法用于检查数组中是否包含指定的元素，它也会返回一个布尔值。
* 函数使用这两个方法来检查用户角色和路由所需角色之间的匹配情况，以确定用户是否有权访问该路由。*/
function hasPermission(roles, route) {
  if (route.meta && route.meta.roles) {
    return roles.some(role => route.meta.roles.includes(role))
  } else {
    return true
  }
}

/**
 * Filter asynchronous routing tables by recursion
 * @param routes asyncRoutes
 * @param roles
 */
/*
* 这段代码是一个 JavaScript 函数，名为 filterAsyncRoutes，用于过滤异步加载的路由。它接受两个参数：routes 和 roles。routes 是一个路由配置对象数组，表示应用程序的所有路由，而 roles 是一个数组，包含用户所具有的角色。

函数的主要作用是过滤路由配置对象数组，只返回那些用户有权限访问的路由。函数遍历 routes 数组中的每个路由配置对象，并使用 hasPermission 函数来检查当前用户是否有访问该路由的权限。如果用户有权限访问该路由，则将该路由配置对象添加到 res 数组中。如果该路由配置对象有 children 属性，则递归调用 filterAsyncRoutes 函数来过滤子路由，并将过滤后的子路由配置对象数组添加到该路由配置对象的 children 属性中。

函数最终返回一个经过过滤后的路由配置对象数组 res。

该函数的实现依赖于 JavaScript 中的对象展开运算符 ... 和数组的 forEach() 方法。函数使用对象展开运算符 ... 来创建一个新的路由配置对象 tmp，以避免修改原始的路由配置对象。函数还使用 forEach() 方法来遍历路由配置对象数组，并对每个路由配置对象进行处理。*/
export function filterAsyncRoutes(routes, roles) {
  const res = []

  routes.forEach(route => {
    const tmp = { ...route }
    if (hasPermission(roles, tmp)) {
      if (tmp.children) {
        tmp.children = filterAsyncRoutes(tmp.children, roles)
      }
      res.push(tmp)
    }
  })

  return res
}

/*
* 这段代码定义了一个 Vuex store 的状态对象 state 和一个 mutation 对象 mutations。下面我来逐一解释这两个对象的内容。

首先是 state 对象，它包含了两个属性：

routes：一个数组，表示应用程序的所有路由。
addRoutes：一个数组，表示异步加载的路由。
接下来是 mutations 对象，它包含了一个名为 SET_ROUTES 的 mutation。该 mutation 接受两个参数：state 和 routes。它的作用是更新 state 对象中的 routes 和 addRoutes 属性。

具体来说，SET_ROUTES mutation 将传入的 routes 参数设置为 state 对象中的 addRoutes 属性，表示异步加载的路由。然后，它使用 JavaScript 的 Array.prototype.concat() 方法将 routes 参数与 constantRoutes 数组合并，并将结果设置为 state 对象中的 routes 属性。这里的 constantRoutes 数组表示静态路由配置，即应用程序的固定路由。

这样做的目的是将异步加载的路由合并到静态路由配置中，以便于在应用程序中进行路由跳转和导航。

总之，这段代码定义了一个 Vuex store 的状态对象和一个 mutation 对象，用于管理应用程序的路由。通过将异步加载的路由合并到静态路由配置中，可以方便地进行路由跳转和导航，并且可以根据用户的角色动态地控制路由访问权限。*/
const state = {
  routes: [],
  addRoutes: []
}

const mutations = {
  SET_ROUTES: (state, routes) => {
    state.addRoutes = routes
    state.routes = constantRoutes.concat(routes)
  }
}

/*
* 这段代码定义了一个 Vuex store 的 actions 对象，包含了一个名为 generateRoutes 的 action。下面我来逐一解释它的内容。

generateRoutes action 接受两个参数：commit 和 roles。commit 是一个 Vuex store 实例的方法，用于提交 mutations。roles 参数表示用户所具有的角色。

generateRoutes action 的作用是根据用户的角色生成可以访问的路由配置，并将其保存到 Vuex store 中。该 action 返回一个 Promise 对象，以便异步地处理路由配置生成的过程。

具体来说，generateRoutes action 首先通过判断用户是否具有 admin 角色来决定返回哪些路由配置。如果用户具有 admin 角色，则返回所有异步加载的路由配置；否则，
* 调用 filterAsyncRoutes 函数来过滤异步加载的路由配置，并返回过滤后的结果。

接着，generateRoutes action 调用 commit 方法来提交 SET_ROUTES mutation，将生成的路由配置保存到 Vuex store 中。

最后，generateRoutes action 返回一个 Promise 对象，以便异步地处理路由配置生成的过程。Promise 对象的解析值是生成的路由配置，以便在异步处理完成后进行处理。

总之，这段代码定义了一个 Vuex store 的 actions 对象，用于根据用户的角色生成可以访问的路由配置，并将其保存到 Vuex store 中，以便于在应用程序中进行路由跳转和导航。*/
const actions = {
  generateRoutes({ commit }, roles) {
    return new Promise(resolve => {
      let accessedRoutes
      if (roles.includes('admin')) {
        accessedRoutes = asyncRoutes || []
      } else {
        accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)
      }
      commit('SET_ROUTES', accessedRoutes)
      resolve(accessedRoutes)
    })
  }
}

/*
* 这段代码导出了一个包含了四个属性的对象，用于创建一个 Vuex store 模块。下面我来逐一解释这四个属性的内容。

首先是 namespaced 属性，它表示该 Vuex store 模块是否启用命名空间。如果将其设置为 true，则在应用程序中访问该模块的状态、
* mutations 和 actions 时需要添加命名空间前缀；否则，可以直接访问该模块的状态、mutations 和 actions，而不需要添加命名空间前缀。

接下来是 state 属性，它表示该 Vuex store 模块的状态。状态是一个对象，包含了该模块的所有状态属性和值。
* 在应用程序中访问该模块的状态时，可以使用 mapState 辅助函数或者直接使用 this.$store.state.moduleName.stateName 的方式进行访问。

然后是 mutations 属性，它表示该 Vuex store 模块的 mutations。mutations 是一个对象
* ，包含了该模块的所有 mutations 函数。在应用程序中提交该模块的 mutations 时，可以使用 mapMutations 辅助函数或者直接使用 this.$store.commit('moduleName/mutationName', payload) 的方式进行提交。

最后是 actions 属性，它表示该 Vuex store 模块的 actions。actions 是一个对象，包
* 含了该模块的所有 actions 函数。在应用程序中调用该模块的 actions 时，可以使用 mapActions 辅助函数或者直接使用 this.$store.dispatch('moduleName/actionName', payload) 的方式进行调用。

总之，这段代码导出了一个包含了四个属性的对象，用于创建一个 Vuex store 模块。通过定义该模块的状态、mutations 和 actions，可以方便地管理应用程序的状态和响应用户的操作。*/
export default {
  namespaced: true,
  state,
  mutations,
  actions
}
